package com.newegg.hardware.benchmark.service;

import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.newegg.hardware.benchmark.model.ItemSpec;
import com.newegg.hardware.benchmark.model.Type;
import com.newegg.hardware.benchmark.util.JSONUtil;

@Service
public class ItemService {

	@Value("${itemservice.host}")
	String server;
	
	@Value("${itemservice.host}")
	String serverOauth;
	
	static RestTemplate template = new RestTemplate();
	
	public ItemSpec getItem(String itemnumber) {
		HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/json; charset=UTF-8"));
        headers.add("Content-Type", "application/json; charset=UTF-8");
        headers.add("Accept", "application/json; charset=UTF-8");
        headers.add("Authorization", "bearer " + serverOauth);
        ResponseEntity<JSONObject> response = template.getForEntity(server + "/content/v1/item/property-value?ItemNumbers=" + itemnumber, JSONObject.class);
		if(response.getStatusCode() != HttpStatus.OK) { return null; }
		JSONArray arrays = response.getBody().getJSONArray("ItemXMLInputSettings");
		if(arrays.size() == 0) { return null; }
		JSONObject data = arrays.getJSONObject(0);
		JSONArray props = data.getJSONArray("PropertyValueSettings");
		Map<String, Object> map = new HashMap<String, Object>();
		JSONUtil.foreach(props, (prop, index)->{
			if(!prop.containsKey("PropertyValues")) { return; }
			JSONArray values = prop.getJSONArray("PropertyValues");
			if(values != null && values.size() > 0) {
				map.put(prop.getString("PropertyName"), values.getJSONObject(0).get("Description"));
			}
		});
		if(map.size() == 0) { return null; }
		String type = data.getString("ItemDescription").toLowerCase();
		if(type.startsWith("cpu")) { return cpuSpec(itemnumber, map); }
		if(type.startsWith("vga")) { return gpuSpec(itemnumber, map); }
		if(type.startsWith("mem")) { return memorySpec(itemnumber, map); }
		if(type.startsWith("hd")) { return diskSpec(itemnumber, map); }
		if(type.startsWith("ssd")) { return diskssdSpec(itemnumber, map); }
		return null;
	}

	private ItemSpec cpuSpec(String itemnumber, Map<String, Object> props) {
		ItemSpec item = new ItemSpec(Type.CPU);
		item.setName(props.get("CPU_Brand") + " " + props.get("CPU_Name"));
		item.append("Name", props.get("CPU_Brand") + " " + props.get("CPU_Name"));
		if(props.containsKey("CPU_# of Cores")) {
			String core = props.get("CPU_# of Cores").toString();
			switch (core) {
				case "Triple-Core": item.append("NumberOfCores", 3); break;
				case "Single-Core": item.append("NumberOfCores", 1); break;
				case "Quad-Core": item.append("NumberOfCores", 4); break;
				case "Dual-Core": item.append("NumberOfCores", 2); break;
				default: 
					try {
						core = core.replace("-Core", "");
						item.append("NumberOfCores", Integer.parseInt(core)); 
					} catch (Exception e) {
						item.append("NumberOfCores", 1); 
					}
				break;
			}
		}else {
			item.append("NumberOfCores", 1);
		}
		if(props.containsKey("CPU_Operating Frequency")) {
			String speed = props.get("CPU_Operating Frequency").toString().toLowerCase().trim();
			if(speed.endsWith("ghz")) {
				try {
					speed = speed.replace("ghz", "").trim();
					item.append("MaxClockSpeed", (int)(Float.parseFloat(speed) * 1000));
				} catch (Exception e) {
					item.append("MaxClockSpeed", 1000);
				}
			}
			if(speed.endsWith("mhz")) {
				try {
					speed = speed.replace("mhz", "").trim();
					item.append("MaxClockSpeed", Integer.parseInt(speed));
				} catch (Exception e) {
					item.append("MaxClockSpeed", 500);
				}
			}
		}else {
			item.append("MaxClockSpeed", 1000);
		}
		item.append("Tech", props.get("CPU_Manufacturing Tech"));
		return item;
	}
	
	private ItemSpec gpuSpec(String itemnumber, Map<String, Object> props) {
		ItemSpec item = new ItemSpec(Type.GPU);
		item.setName(props.get("VGA_GPU").toString());
		item.append("Name", props.get("VGA_GPU"));
		item.append("AdapterCompatibility", "");
		item.append("CUDA", props.get("VGA_CUDA Cores"));
		return item;
	}
	
	private ItemSpec memorySpec(String itemnumber, Map<String, Object> props) {
		ItemSpec item = new ItemSpec(Type.MEMORY);
		item.setName(props.get("MEM_Model").toString());
		item.append("PartNumber", props.get("MEM_Model"));
		if(props.containsKey("MEM_Speed")) {
			String speed = props.get("MEM_Speed").toString().toLowerCase().trim();
			speed = speed.split(" ")[1];
			try {
				item.append("ConfiguredClockSpeed", Integer.parseInt(speed));
			} catch (Exception e) {
				item.append("ConfiguredClockSpeed", 2400);
			}
		}else {
			item.append("ConfiguredClockSpeed", 2400);
		}
		if(props.containsKey("MEM_Capacity")) {
			String speed = props.get("MEM_Capacity").toString().toLowerCase().trim();
			try {
				if(speed.indexOf("g") != -1) {
					speed = speed.substring(0, speed.indexOf("g")).trim();
					item.append("Capacity", Integer.parseInt(speed) * 1024 * 1024);
				}
				if(speed.indexOf("t") != -1) {
					speed = speed.substring(0, speed.indexOf("t")).trim();
					item.append("Capacity", Integer.parseInt(speed) * 1024 * 1024 * 1024);
				}
				if(speed.indexOf("m") != -1) {
					speed = speed.substring(0, speed.indexOf("m")).trim();
					item.append("Capacity", Integer.parseInt(speed) * 1024);
				}
			} catch (Exception e) {
				item.append("ConfiguredClockSpeed", 4 * 1024 * 1024);
			}
		}else {
			item.append("ConfiguredClockSpeed", 4 * 1024 * 1024);
		}
		return item;
	}
	
	private ItemSpec diskSpec(String itemnumber, Map<String, Object> props) {
		ItemSpec item = new ItemSpec(Type.DISK);
		if(props.containsKey("HDD_Series")) {
			item.append("Model", props.get("HDD_Series"));
			item.setName(props.get("HDD_Series").toString());
		}else if(props.containsKey("HDD_Model")) {
			item.append("Model", props.get("HDD_Model"));
			item.setName(props.get("HDD_Model").toString());
		}
		return item;
	}
	
	private ItemSpec diskssdSpec(String itemnumber, Map<String, Object> props) {
		ItemSpec item = new ItemSpec(Type.DISK);
		if(props.containsKey("SSD_Series")) {
			item.append("Model", props.get("SSD_Series"));
			item.setName(props.get("SSD_Series").toString());
		}else if(props.containsKey("SSD_Model")) {
			item.append("Model", props.get("SSD_Model"));
			item.setName(props.get("SSD_Model").toString());
		}
		item.append("DiviceType", "SSD");
		return item;
	}
}
